package com.zhiche.wms.service.inbound.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.utils.SnowFlakeId;
import com.zhiche.wms.core.utils.qiniu.QiNiuUtil;
import com.zhiche.wms.domain.mapper.inbound.InboundInspectLineMapper;
import com.zhiche.wms.domain.model.inbound.InboundInspectHeader;
import com.zhiche.wms.domain.model.inbound.InboundInspectLine;
import com.zhiche.wms.domain.model.inbound.InboundNoticeHeader;
import com.zhiche.wms.domain.model.inbound.InboundNoticeLine;
import com.zhiche.wms.domain.model.opbaas.ExceptionRegisterPicture;
import com.zhiche.wms.dto.inbound.InboundInspectDTO;
import com.zhiche.wms.dto.inbound.InboundNoticeDTO;
import com.zhiche.wms.dto.opbaas.paramdto.CommonConditionParamDTO;
import com.zhiche.wms.dto.opbaas.resultdto.PictureWithExcpDescDTO;
import com.zhiche.wms.service.base.IBusinessDocNumberService;
import com.zhiche.wms.service.constant.Status;
import com.zhiche.wms.service.inbound.IInboundInspectHeaderService;
import com.zhiche.wms.service.inbound.IInboundInspectLineService;
import com.zhiche.wms.service.inbound.IInboundNoticeHeaderService;
import com.zhiche.wms.service.inbound.IInboundNoticeLineService;
import com.zhiche.wms.service.opbaas.ExceptionToOTMService;
import com.zhiche.wms.service.opbaas.IExceptionRegisterPictureService;
import com.zhiche.wms.service.sys.IUserService;
import com.zhiche.wms.service.utils.CommonMethod;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 入库质检单明细 服务实现类
 * </p>
 *
 * @author zhaoguixin
 * @since 2018-06-22
 */
@Service
public class InboundInspectLineServiceImpl extends ServiceImpl<InboundInspectLineMapper, InboundInspectLine> implements IInboundInspectLineService {

    @Autowired
    private SnowFlakeId snowFlakeId;
    @Autowired
    private IInboundNoticeLineService inboundNoticeLineService;
    @Autowired
    private IInboundNoticeHeaderService inboundNoticeHeaderService;
    @Autowired
    private IBusinessDocNumberService businessDocNumberService;
    @Autowired
    private IInboundInspectHeaderService iInboundInspectHeaderService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IExceptionRegisterPictureService pictureService;

    @Autowired
    private ExceptionToOTMService exceptionToOTMService;

    /**
     * 查询质检信息集合
     */
    public Page<InboundInspectDTO> queryList(String key, Long houseId, Integer size, Integer current) {
        if (Strings.isNullOrEmpty(key)) throw new BaseException("订单号或车架号为空");
        //创建page分页对象
        Page<InboundInspectDTO> page = new Page<>(current, size);
        //创建模糊条件对象
        EntityWrapper<InboundInspectDTO> ew = new EntityWrapper<>();
        //增加模糊条件
        ew.eq("store_house_id", houseId)
                .eq("status", Status.Inbound.NOT)
                .notIn("status", TableStatusEnum.STATUS_50.getCode())
                .andNew()
                .like("owner_order_no", key)
                .or()
                .like("lot_No1", key)
                .or()
                .eq("qr_code", key)
                .orderBy("gmt_create", false)
                .orderBy("id", false);
        //保存获取到的质检信息集合
        List<InboundInspectDTO> inboundInspectDTOS = this.baseMapper.queryInbound(page, ew);
        for (InboundInspectDTO inspect :
                inboundInspectDTOS) {
            //遍历将返回为空的状态修改为0
            if (Strings.isNullOrEmpty(inspect.getStatus())) inspect.setStatus("0");
        }
        page.setRecords(inboundInspectDTOS);
        return page;
    }

    /**
     * 获取质检信息详明（若不存在生成后在返回）
     */
    public InboundInspectDTO updateInspectInfo(String key, Long houseId) {
        //检测key是否为空
        if (Strings.isNullOrEmpty(key)) {
            throw new BaseException("订单号或车架号为空");
        }

        //将key值进行转换
        Long key1 = new Long(key);
        //查询匹配Inspect信息
        InboundInspectDTO existsDto = this.baseMapper.getInInspectLine(key1, houseId);
        //若没有匹配信息，进行生成
        if (existsDto == null) {
            //获取对应noticeLine对象与noticeHeader对象
            InboundNoticeLine noticeLine = inboundNoticeLineService.selectById(key1);
            InboundNoticeHeader noticeHeader = inboundNoticeHeaderService.selectById(noticeLine.getHeaderId());

            //创建inspectHeader质检单详明存储区域
            InboundInspectHeader inspectHeader = new InboundInspectHeader();
            //质检单头信息匹配开始
            //将noticeHeader对象对应值存入inspectHeader
            BeanUtils.copyProperties(noticeHeader, inspectHeader);
            inspectHeader.setId(snowFlakeId.nextId());
            inspectHeader.setNoticeId(noticeHeader.getId());
            inspectHeader.setInspectNo(businessDocNumberService.getInboundInspectNo());
            inspectHeader.setOrderDate(new Date());
            inspectHeader.setInspector(userService.getLoginUser().getName());
            inspectHeader.setLineCount(1);
            inspectHeader.setIsFinish(0);
            inspectHeader.setRecvSumQty(new BigDecimal(1));
            inspectHeader.setDamagedSumQty(new BigDecimal(0));
            inspectHeader.setQualifiedSumQty(new BigDecimal(0));
            inspectHeader.setStatus(null);
            inspectHeader.setUserCreate(userService.getLoginUser().getName());
            inspectHeader.setGmtCreate(null);
            inspectHeader.setGmtModified(null);
            //判断新增是否成功
            if (!iInboundInspectHeaderService.insert(inspectHeader)) {
                //取反后   如果值新增失败报出异常
                throw new BaseException("质检单头创建失败");
            }

            //创建inspectLine质检单详明存储区域
            InboundInspectLine inspectLine = new InboundInspectLine();
            //复制参数
            BeanUtils.copyProperties(noticeLine, inspectLine);
            //修改不匹配参数
            inspectLine.setId(snowFlakeId.nextId());
            inspectLine.setHeaderId(inspectHeader.getId());
            inspectLine.setNoticeLineId(noticeLine.getId());

            inspectLine.setRecvQty(new BigDecimal(1)); //收货数量
            inspectLine.setStatus("0");
            inspectLine.setDealMethod(null);
            inspectLine.setGmtCreate(null);
            inspectLine.setGmtModified(null);
            //判断质检单详明新增结果
            if (!this.insert(inspectLine)) throw new BaseException("质检单明细创建失败");  //若新增失败报出异常，否则继续执行
            existsDto = this.baseMapper.getInInspectLine(key1, houseId);
            //查询该车是否异常发运
            String send = exceptionToOTMService.isSend(existsDto.getLotNo1(), existsDto.getStoreHouseName());
            if (!StringUtils.isEmpty(send))existsDto.setIsCanSend(send);

        }
        if (Objects.isNull(existsDto)) throw new BaseException("未查找到匹配质检单");
        return existsDto;
    }

    /**
     * 根据匹配二维码的方式进行详明查询
     */
    public InboundInspectDTO updateInspectBykey(String key, Long houseId) {
        if (Strings.isNullOrEmpty(key)) throw new BaseException("订单号或车架号为空");
        //查询匹配二维码的通知单信息
        InboundNoticeDTO noticeDTO = inboundNoticeLineService.selectInboundByQrCode(key, houseId);
        if (Objects.isNull(noticeDTO)) throw new BaseException("未找到对应信息");
        //通过通知单id调用通过id查询的方法
        return this.updateInspectInfo(noticeDTO.getId().toString(), houseId);
    }

    /**
     * 完成质检
     */
    public void updateInspectStatus (String key, Long houseId, Integer status, String isCanSend, String orderReleaseGid,String estimatedProcessingTime) {
        if (Strings.isNullOrEmpty(key)) throw new BaseException("id号为空");
        Long key1 = new Long(key);
        //修改详明的状态信息
        if (!(this.baseMapper.updateStatus(key1, houseId, status) > 0)) throw new BaseException("新增失败");
        //查询所有该header下的结果集
        InboundInspectLine inspectLine = this.selectById(key);
        EntityWrapper<InboundInspectLine> ew = new EntityWrapper<>();
        ew.eq("header_id", inspectLine.getHeaderId());
        List<InboundInspectLine> inboundInspectLines = this.selectList(ew);

        //合格数量
        BigDecimal qualifiedSum = new BigDecimal(0);
        //破碎数量
        BigDecimal damagedSum = new BigDecimal(0);
        //准备遍历为第一行
        boolean isOne = true;
        String vstatus = "";
        for (InboundInspectLine inspectLineitem : inboundInspectLines) {
            //第一次为标识赋值
            if (isOne) {
                if (Strings.isNullOrEmpty(inspectLineitem.getStatus())) {
                    continue;
                } else {
                    //将第一个状态保存下来
                    isOne = false;
                    vstatus = inspectLineitem.getStatus();
                }
            }
            //判断状态为匹配状态赋值
            if ("10".equals(inspectLineitem.getStatus())) {//该明细状态为10，为单头合格数量加量
                if (!Objects.isNull(inspectLineitem.getRecvQty()))
                    qualifiedSum = qualifiedSum.add(inspectLineitem.getRecvQty());
            } else if ("30".equals(inspectLineitem.getStatus())) {//该明细状态为30，为单头破损数量加量
                if (!Objects.isNull(inspectLineitem.getRecvQty()))
                    damagedSum = damagedSum.add(inspectLineitem.getRecvQty());
            }
            //判断集合中是否有不相同的
            if (!vstatus.equals(inspectLineitem.getStatus())) {
                //存在状态不同，就将头状态标识为“部分通过”
                vstatus = "20";
            }
        }
        //保存状态标识是否正常
        if (Strings.isNullOrEmpty(vstatus)) throw new BaseException("质检单详明状态出现错误");
        //修改头信息
        iInboundInspectHeaderService.updateStatus(inspectLine.getHeaderId(), houseId, new Integer(vstatus), qualifiedSum, damagedSum);

        //异常信息传送otm   --- update by CAIHUA 2019-09-16
        if (StringUtils.isNotEmpty(isCanSend)) {
            CommonConditionParamDTO commonConditionParamDTO = new CommonConditionParamDTO();
            Map<String, String> map = new HashMap<>();
            map.put("orderReleaseGid",orderReleaseGid);
            map.put("houseId", String.valueOf(houseId));
            map.put("lotNo1", inspectLine.getLotNo1());
            map.put("isCanSend", isCanSend);
            map.put("estimatedProcessingTime", estimatedProcessingTime);
            commonConditionParamDTO.setCondition(map);
            List<CommonConditionParamDTO> conditions = exceptionToOTMService.setToOtmParam(commonConditionParamDTO);
            if (CollectionUtils.isNotEmpty(conditions)) {
                for (CommonConditionParamDTO otmParam : conditions) {
                    exceptionToOTMService.isCanSend(otmParam);
                }
            }
        }
    }

    /**
     * 入库质检查询 -- 列表查询
     */
    @Override
    public Page<InboundInspectDTO> listInspectPage(Page<InboundInspectDTO> page) {
        if (page == null) {
            throw new BaseException("page参数不能为空");
        }
        Map<String, Object> cn = page.getCondition();
        if (cn == null || cn.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        if (cn.get("houseId") == null || StringUtils.isBlank(cn.get("houseId").toString())) {
            throw new BaseException("仓库信息不能为空");
        }
        //设置条件
        HashMap<String, Object> params = Maps.newHashMap();
        buildCondition(cn, params);
        params.put("start", page.getOffsetCurrent());
        params.put("end", page.getSize());
        params.put("statusNe", TableStatusEnum.STATUS_50.getCode());
        baseMapper.updateSQLMode();
        List<InboundInspectDTO> list = baseMapper.listInspectPage(params);
        int count = baseMapper.countInspectPage(params);
        page.setTotal(count);
        if (CollectionUtils.isNotEmpty(list)) {
            // 设置异常信息
            for (InboundInspectDTO dto : list) {
                StringBuilder sb = new StringBuilder();
                setMissStr(dto, sb );
                if (StringUtils.isNotBlank(dto.getExDescStr())) {
                    dto.setEx_arr(dto.getExDescStr().split(","));
                }
                ArrayList<PictureWithExcpDescDTO> infos = Lists.newArrayList();
                if (StringUtils.isNotBlank(dto.getExcpIds())) {
                    //质损 每一个异常项目的图片
                    String[] ex_id = dto.getExcpIds().split(",");
                    for (String excpId : ex_id) {
                        EntityWrapper<ExceptionRegisterPicture> picEW = new EntityWrapper<>();
                        picEW.eq("exception_id", excpId)
                                .eq("pic_status", TableStatusEnum.STATUS_10.getCode());
                        List<PictureWithExcpDescDTO> pics = pictureService.listPicsAndDesc(picEW);
                        if (CollectionUtils.isNotEmpty(pics)) {
                            PictureWithExcpDescDTO descDTO = pics.get(0);
                            List<ExceptionRegisterPicture> pictures = descDTO.getPictures();
                            if (CollectionUtils.isNotEmpty(pictures)) {
                                for (ExceptionRegisterPicture pic : pictures) {
                                    pic.setPicUrl(QiNiuUtil.generateDownloadURL(pic.getPicKey(), ""));
                                }
                            }
                            infos.add(descDTO);
                        }
                    }
                    if (CollectionUtils.isNotEmpty(infos)) {
                        dto.setPicInfo(infos);
                    }
                }
            }
        }
        page.setRecords(list);
        return page;
    }

    /**
     * 入库质检导出
     */
    @Override
    public List<InboundInspectDTO> queryExportInspect(Map<String, Object> condition) {
        if (condition == null || condition.isEmpty()) {
            throw new BaseException("参数不能为空");
        }
        if (condition.get("houseId") == null || StringUtils.isBlank(condition.get("houseId").toString())) {
            throw new BaseException("仓库信息不能为空");
        }
        HashMap<String, Object> params = Maps.newHashMap();
        buildCondition(condition, params);
        baseMapper.updateSQLMode();
        List<InboundInspectDTO> list = baseMapper.queryExportInspect(params);
        // 设置异常信息
        for (InboundInspectDTO dto : list) {
            StringBuilder sb = new StringBuilder();
            setMissStr(dto, sb);
        }
        return list;
    }

    private void setMissStr(InboundInspectDTO dto, StringBuilder sb) {
        if (StringUtils.isNotBlank(dto.getMissDescStr())) {
            String[] miss_arr = dto.getMissDescStr().split(",");
            dto.setMiss_arr(miss_arr);
            for (String str : miss_arr) {
                sb.append("缺少_").append(str).append(",");
            }
            dto.setMissDescStr(sb.substring(0, sb.length() - 1));
        }
    }

    private void buildCondition(Map<String, Object> cn, HashMap<String, Object> params) {
        params.put("houseId", cn.get("houseId").toString());
        if (cn.get("ownerId") != null && StringUtils.isNotBlank(cn.get("ownerId").toString())) {
            params.put("ownerId", cn.get("ownerId").toString());
        }
        if (cn.get("lotNo1") != null && StringUtils.isNotBlank(cn.get("lotNo1").toString())) {
            String vin = cn.get("lotNo1").toString();
           /* String[] split = vin.split(",");
            List<String> vins = Arrays.asList(split);*/
            List<String> vins = Arrays.asList(CommonMethod.setVins(vin));
            params.put("lotNo1", vins);
        }
        if (cn.get("orderNo") != null && StringUtils.isNotBlank(cn.get("orderNo").toString())) {
            params.put("orderNo", cn.get("orderNo").toString());
        }
        if (cn.get("startDate") != null && StringUtils.isNotBlank(cn.get("startDate").toString())) {
            params.put("startDate", cn.get("startDate").toString());
        }
        if (cn.get("endDate") != null && StringUtils.isNotBlank(cn.get("endDate").toString())) {
            params.put("endDate", cn.get("endDate").toString());
        }
        if (cn.get("carrierName") != null && StringUtils.isNotBlank(cn.get("carrierName").toString())) {
            params.put("carrierName", "%" + cn.get("carrierName").toString() + "%");
        }
        params.put("taskNode", TableStatusEnum.STATUS_40.getCode());
        params.put("status10", TableStatusEnum.STATUS_10.getCode());
        params.put("status20", TableStatusEnum.STATUS_20.getCode());
        params.put("groupBy", "a.lot_no1");
        params.put("orderBy", "a.id desc");
    }
}
